% 参数设置
N = 64;             % FFT点数
cp_len = 16;        % 循环前缀长度
num_symbols = 10;   % OFDM符号数
delta_tau_true = 3; % 真实的时间偏移（采样点）
SNR_dB = 30;        % 信噪比（忽略噪声设为 inf）

% 生成发送信号（手动 QPSK 调制）
data = randi([0,1], 2*N, num_symbols);
symbol_table = [ (1+1j), (-1+1j), (-1-1j), (1-1j) ] / sqrt(2); % Gray 编码
tx_symbols = zeros(N, num_symbols);

for col = 1:num_symbols
    bits = data(:, col);
    bits_grouped = reshape(bits, 2, N);       % 每列两个比特 [b1; b2]
    indices = bits_grouped(1,:)*2 + bits_grouped(2,:); % 计算索引 (0~3)
    tx_symbols(:, col) = symbol_table(indices + 1).';  % 映射为 QPSK 符号
end

% 生成 OFDM 时域信号
tx_ofdm = ifft(tx_symbols, N);                   % IFFT
tx_ofdm = [tx_ofdm(end-cp_len+1:end, :); tx_ofdm]; % 添加循环前缀

% 人为添加时间偏移（循环右移模拟延迟）
rx_ofdm = circshift(tx_ofdm, delta_tau_true, 1); % 关键修改：循环移位

% 添加噪声（手动实现）
if SNR_dB ~= inf
    signal_power = mean(abs(rx_ofdm(:)).^2);
    noise_power = signal_power / (10^(SNR_dB/10));
    noise = sqrt(noise_power/2) * (randn(size(rx_ofdm)) + 1j*randn(size(rx_ofdm)));
    rx_ofdm = rx_ofdm + noise;
end

% 接收端处理（去循环前缀 + FFT）
rx_ofdm_symbols = rx_ofdm(cp_len+1:end, :); % 去 CP
rx_symbols = fft(rx_ofdm_symbols, N);        % FFT

% 信道估计（理想信道假设）
H_est = rx_symbols ./ tx_symbols;

% 计算相邻子载波相位差
H_ratio = H_est(2:end, :) ./ H_est(1:end-1, :);
phase_diff = angle(H_ratio(:)); % 直接计算相位差
phase_diff = unwrap(phase_diff); % 解包相位差

% 平均相位差并估计时间偏移
mean_phase_diff = mean(phase_diff(:));
delta_tau_est = -mean_phase_diff * N / (2*pi); % 关键修改：符号修正

% 显示结果
fprintf('真实时间偏移: %.2f 采样点\n', delta_tau_true);
fprintf('估计时间偏移: %.2f 采样点\n', delta_tau_est);